package org.gikolet.util;

import java.lang.reflect.Field;

public final class ReflectionString {
	private ReflectionString() {
	}

	public static String toString(Object obj) {

		try {
			Field[] fields = obj.getClass().getDeclaredFields();
			Field.setAccessible(fields, true);

			StringBuilder sb = new StringBuilder();

			int fieldLoopCount = fields.length - 1;
			for (int i = 0; i < fieldLoopCount; i++) {
				Field f = fields[i];

				sb.append(f.getName()).append('=');
				append(f.getDeclaringClass(), f.get(obj), sb);
				sb.append(", ");
			}

			if (fieldLoopCount >= 0) {
				Field f = fields[fields.length - 1];

				sb.append(f.getName()).append('=');
				append(f.getDeclaringClass(), f.get(obj), sb);
			}

			return sb.toString();

		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		}
	}

	private static void append(Class<?> clazz, Object obj, StringBuilder sb) {
		if (clazz.isArray()) {

			Object[] objs = (Object[]) primitiveArrayToObjectArray(obj);

			sb.append("[ ");
			int objLoopCount = objs.length - 1;
			for (int i = 0; i < objLoopCount; i++) {
				append(objs[i].getClass(), objs[i], sb);
				sb.append(", ");
			}

			if (objLoopCount >= 0) {
				Object o = objs[objs.length - 1];
				append(o.getClass(), o, sb);
			}

			sb.append(" ]");

		} else {
			sb.append(obj);
		}
	}

	private static Object primitiveArrayToObjectArray(Object obj) {
		Object result = obj;

		if (obj instanceof boolean[]) {
			boolean[] bs = (boolean[]) obj;
			Boolean[] bos = new Boolean[bs.length];
			for (int i = 0; i < bos.length; i++) {
				bos[i] = bs[i];
			}

			result = bos;

		} else if (obj instanceof byte[]) {
			byte[] bs = (byte[]) obj;
			Byte[] bos = new Byte[bs.length];
			for (int i = 0; i < bos.length; i++) {
				bos[i] = bs[i];
			}

			result = bos;

		} else if (obj instanceof short[]) {
			short[] ss = (short[]) obj;
			Short[] sos = new Short[ss.length];
			for (int i = 0; i < sos.length; i++) {
				sos[i] = ss[i];
			}

			result = sos;

		} else if (obj instanceof char[]) {
			char[] cs = (char[]) obj;
			Character[] cos = new Character[cs.length];
			for (int i = 0; i < cos.length; i++) {
				cos[i] = cs[i];
			}

			result = cos;

		} else if (obj instanceof int[]) {
			int[] is = (int[]) obj;
			Integer[] ios = new Integer[is.length];
			for (int i = 0; i < ios.length; i++) {
				ios[i] = is[i];
			}

			result = ios;

		} else if (obj instanceof float[]) {
			float[] fs = (float[]) obj;
			Float[] fos = new Float[fs.length];
			for (int i = 0; i < fos.length; i++) {
				fos[i] = fs[i];
			}

			result = fos;

		} else if (obj instanceof double[]) {
			double[] ds = (double[]) obj;
			Double[] dos = new Double[ds.length];
			for (int i = 0; i < dos.length; i++) {
				dos[i] = ds[i];
			}

			result = dos;
		}

		return result;
	}
}
